package com.foreveross.crawl.adapter.sub.impl20140402.v3.travelsky;

import java.util.List;
import java.util.Random;

import org.apache.http.client.methods.HttpPost;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.foreveross.crawl.adapter.PlaneInfoEntityBuilder;
import com.foreveross.crawl.adapter.sub.impl20140402.v3.TravelskyAdapter;
import com.foreveross.crawl.common.util.RegHtmlUtil;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.TransitEntity;
import com.foreveross.crawl.domain.airfreight.single.SinglePlaneInfoEntity;
import com.foreveross.crawl.exception.FlightInfoNotFoundException;
import com.foreveross.taskservice.common.bean.TaskModel;
import com.google.common.collect.Lists;

/**
 * 国内单程实现。
 *
 * @author luomingliang@foreveross.com
 * @version 1.0.0
 * @date 2014/08/13
 */
public class TravelskyInlandOneWayAdapter extends TravelskyAdapter {
	/** ******************************** Params *********************************************** */
	private static final boolean is_get_more_cabin = true; // 是否获取更多舱位。

	/** ******************************** Constructor *********************************************** */
	private TravelskyAdapter adapter;
	private TaskModel taskQueue;
	public TravelskyInlandOneWayAdapter(TravelskyAdapter adapter, TaskModel taskQueue) {
		super(taskQueue);
		this.taskQueue = taskQueue;
		this.adapter = adapter;
	}

	/** ******************************** Fetch *********************************************** */

	@Override
	public String getUrl() throws Exception {
		StringBuffer url = new StringBuffer("http://bk.travelsky.com/bkair/reservation/flightQuery.do?adultNum=1");
		url.append("&destCity=").append(taskQueue.getToCity());
		url.append("&orgCity=").append(taskQueue.getFromCity());
		url.append("&returnDate=").append(taskQueue.getFlightDate());
		url.append("&takeoffDate=").append(taskQueue.getFlightDate());
		url.append("&tripType=0");// .append(taskQueue.getIsReturn());
		url.append("&queryFlightRequestId=").append(requestId);
		return url.toString();
	}

	/**
	 * 抓取页面数据 。
	 * 
	 * @return
	 * @throws Exception
	 */
	public Object fetch() throws Exception {
		String page = null;
		try {
			this.setCookie();
			String url = getUrl();
			page = super.excuteRequest(new HttpPost(url));
			validateFetch(page);
			adapter.appendPageContents(page);
			queryPage = imageUtils.htmlPage(url); // 保存一下HttpPage，以便解析价格
			rollbackProxyIp(true);
		} catch (Exception e) {
			rollbackProxyIp(false);
			logger.error(String.format("页面数据抓取失败：%s", e.getMessage()));
			throw e;
		} finally {}
		return page;
	}

	/** ******************************** Parse *********************************************** */

	/** 单程程数据解析 */
	public Object parse(Object fetchObject) throws Exception {
		List<SinglePlaneInfoEntity> toFlights = Lists.newArrayList();
		String page = fetchObject.toString();
		try {
			Document document = Jsoup.parse(page);
			Element goElems = document.getElementById("result_table");
			toFlights = parsePlaneInfos(goElems); // 去程航班集合

			Element interElems = document.getElementById("interresult_table"); // 解析推荐联程
			toFlights.addAll(parseInterPlaneInfos(interElems)); // 如果又有自由组合又有推荐联程，则两个合并。
			PlaneInfoEntityBuilder.buildLimitPrice(toFlights);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("数据解析出错：" + e.getMessage());
			throw e;
		}
		return toFlights;
	}

	/**
	 * 解析联程航班 。
	 * 
	 * @return
	 * @throws Exception
	 */
	private List<SinglePlaneInfoEntity> parseInterPlaneInfos(Element elem) throws Exception {
		List<SinglePlaneInfoEntity> planeInfos = Lists.newArrayList();
		String[] flightNos = null;
		String[] flightDates = null;
		String[] fromCitys = null;
		String[] fromTimes = null;
		String[] toCitys = null;
		String[] endTimes = null;
		String[] types = null;
		try {

			Elements trs = elem.select("tr");
			for (int i = 0; i < trs.size(); i++) { // 1 4 7 11航班行
				if (i % 3 != 1) continue;
				SinglePlaneInfoEntity planeInfo = null;
				Elements tds = trs.get(i).select("td");
				Elements flightNoElems = tds.get(0).select("img");
				if (flightNoElems.size() == 0) continue;
				flightNos = new String[] { parseImg(flightNoElems.get(0), "1"), parseImg(flightNoElems.get(1), "1") };
				flightDates = tds.get(1).text().split(" "); // 航班日期S
				fromCitys = tds.get(2).text().split(" ");// 起飞城市
				Elements fromCityElems = tds.get(2).getElementsByTag("img");
				fromTimes = new String[] { parseImg(fromCityElems.get(0), "2"), parseImg(fromCityElems.get(1), "2") };// 起飞时间
				toCitys = tds.get(3).text().split(" ");// 降落城市
				Elements toCityElems = tds.get(3).getElementsByTag("img");
				endTimes = new String[] { parseImg(toCityElems.get(0), "2"), parseImg(toCityElems.get(1), "2") };// 降落时间
				types = tds.get(4).text().split(" ");

				planeInfo = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "BK", "奥凯", "奥凯航空", null, null, flightNos[0], null, null, null, types[0], SinglePlaneInfoEntity.class);
				planeInfo.setStartTime(PlaneInfoEntityBuilder.getFlightTime(flightDates[0], fromTimes[0]));
				planeInfo.setEndTime(PlaneInfoEntityBuilder.getFlightTime(flightDates[1], endTimes[1]));

				List<TransitEntity> trans = Lists.newArrayList();
				for (int j = 0; j < flightNoElems.size(); j++) {
					TransitEntity tran = PlaneInfoEntityBuilder.buildTransitEntity(flightNos[j], flightNos[j], "BK", "奥凯", "奥凯航空", null, fromCitys[j], null, toCitys[j], types[j]);
					tran.setStartTime(PlaneInfoEntityBuilder.getFlightTime(flightDates[j], fromTimes[j]));
					tran.setEndTime(PlaneInfoEntityBuilder.getFlightTime(flightDates[j], endTimes[j]));
					trans.add(tran);
				}

				planeInfo.getCabins().addAll(getInterCabins(tds.get(6)));// 最低舱位。

				// 是否获取更多舱位。
				if (is_get_more_cabin) {
					planeInfo.getCabins().addAll(getInterCabins(trs.get(i + 1)));
				}
				planeInfo.getTransits().addAll(trans);
				planeInfos.add(planeInfo);

			}
		} finally {
			flightNos = null;
			flightDates = null;
			fromCitys = null;
			fromTimes = null;
			toCitys = null;
			endTimes = null;
			types = null;
		}

		return planeInfos;
	}

	/** 解析出航班信息。 */
	private List<SinglePlaneInfoEntity> parsePlaneInfos(Element elem) throws Exception {
		List<SinglePlaneInfoEntity> planeInfos = Lists.newArrayList();

		Elements trs = elem.getElementsByTag("tr");
		for (int i = 0; i < trs.size(); i++) { // 1 4 7 11航班行
			if (i % 3 != 1) continue;
			SinglePlaneInfoEntity planeInfo = null;

			Element tr = trs.get(i);
			Elements tds = tr.getElementsByTag("td");
			String flightNo = parseImg(tds.get(0), "1");// 航班号
			String depTime = parseImg(tds.get(1), "2");// 起飞时间
			String arrTime = parseImg(tds.get(2), "2");// 到达时间
			String type = tds.get(4).text();
			planeInfo = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "BK", " 奥凯", "奥凯航空", depTime, arrTime, flightNo, null, null, null, type, SinglePlaneInfoEntity.class);
			List<CabinEntity> cabins = getCabins(tds.get(5), tds.get(6), tds.get(7), tds.get(8));
			if (is_get_more_cabin) {
				cabins.addAll(getMoreCabins(trs.get(i + 1)));
			}
			planeInfo.getCabins().addAll(cabins);
			planeInfos.add(planeInfo);
		}
		return planeInfos;
	}

	/** 获取联程更多舱位。 */
	private List<CabinEntity> getInterCabins(Element element) throws Exception {
		List<CabinEntity> cabins = Lists.newArrayList();
		String reg = "interShowEI.*?&quot;([A-Z]{2})&quot;.*?&quot;(\\d{2,}?)\\.000000&quot;,&quot;(\\d{2,}?)\\.000000&quot;\\).*?src=\"(.*?)\"\\s/>";
		List<List<String>> lists = RegHtmlUtil.retrieveLinkss(element.toString(), reg);
		int i = 0;
		for (List<String> list : lists) {
			// if (i++ > 10) continue;
			CabinEntity cabin = null;
			try {
				String cabinName = list.get(1) + "舱";
				String tax = (PlaneInfoEntityBuilder.getDouble(list.get(2)) + PlaneInfoEntityBuilder.getDouble(list.get(3))) + ""; // 税费
				String price = parseImg(list.get(4), "0"); // 解析图片价 格。
				Double amount = Double.parseDouble(tax) + Double.parseDouble(price);
				cabin = PlaneInfoEntityBuilder.buildCabinInfo(cabinName, null, cabinName, tax, price, amount + "", null, null, CabinEntity.class);
				cabins.add(cabin);
			} catch (Exception e) {
				logger.error("推荐舱位获取失败:" + e.getMessage());
			}
		}
		return cabins;
	}

	/** 获取舱位。 */
	private List<CabinEntity> getCabins(Element... elements) throws Exception {
		List<CabinEntity> cabins = Lists.newArrayList();
		for (int i = 0; i < elements.length; i++) {
			try {
				CabinEntity cabin = null;
				Element ele = elements[i];
				if ("--".equals(ele.text())) continue; // 没有价格。

				Elements eles = ele.getAllElements();
				String[] val = eles.get(1).attr("value").split("/");
				String cabinName = cabinNames.get(i);
				String subcabin = val[2];
				String tuigaiqian = eles.get(1).attr("title");
				Double tax = Double.parseDouble(val[6]) + Double.parseDouble(val[7]);
				String price = parseImg(eles.get(2), "0");
				Double amount = tax + Double.parseDouble(price);
				cabin = PlaneInfoEntityBuilder.buildCabinInfo(cabinName, subcabin, cabinName, tax + "", price, amount + "", tuigaiqian, null, CabinEntity.class);
				cabins.add(cabin);
			} catch (Exception e) {
				logger.error("舱位获取失败:" + e.getMessage());
			}
		}
		return cabins;
	}

	/** 获取更多舱位。 */
	private List<CabinEntity> getMoreCabins(Element element) throws Exception {
		List<CabinEntity> cabins = Lists.newArrayList();
		String reg = "class=\"more\">.*?value=\"(.*?)\".*?<img src=\"(.*?)\"";
		List<List<String>> lists = RegHtmlUtil.retrieveLinkss(element.toString(), reg);
		for (List<String> list : lists) {
			CabinEntity cabin = null;
			String[] val = list.get(1).split("/");
			String cabinName = val[2] + "舱";
			String tuigaiqian = "";// list.get(2);
			String subcabin = cabinName.substring(0, 1);// list.get(3);
			Double tax = Double.parseDouble(val[6]) + Double.parseDouble(val[7]);
			String price = parseImg(list.get(2), "0");
			Double amount = tax + Double.parseDouble(price);
			cabin = PlaneInfoEntityBuilder.buildCabinInfo(cabinName, subcabin, cabinName, tax + "", price, amount + "", tuigaiqian, null, CabinEntity.class);
			cabins.add(cabin);
		}
		return cabins;
	}

	@Override
	public boolean validateFetch(Object fetchObject) throws Exception {
		if (fetchObject == null) {
			throw new Exception("抓取到的数据为空！");
		}
		if (RegHtmlUtil.regMathcher(fetchObject.toString(), "公共的出错页面")) {
			throw new Exception("服务器忙，请稍后再试 ");
		}
		
//		if (RegHtmlUtil.regMathcher(fetchObject.toString(), "没有相应的航班")) {
//			throw new FlightInfoNotFoundException();
//		}
		List<String> list=RegHtmlUtil.regStrBeforeIndex(fetchObject.toString(), "<span>没有相应的航班</span>(.+?)没有相应的航班", 1);
		if(null!=list && list.size()>0){
			throw new FlightInfoNotFoundException();
		}
		
		return true;
	}
}